package org.semanticflash.rdf.values
{
	
	import com.adobe.crypto.MD5;
	import com.bigflexlib.core.markers.IValueSingleton;
	
	import mx.core.IUID;
	import mx.utils.UIDUtil;
	

	/**
	 * 
	 * <pre>
	 * 
	 * -- RDFValue ( abstract )
	 * ---- IRI
	 * ---- RDFLiteral ( abstract )
	 * ------ RDFPlainLiteral
	 * ------ RDFTypedLiteral
	 * ------ RDFLangLiteral
	 * 
	 * </pre>
	 * 
	 * 
	 * <p>
	 * <b>WARNING:</b>
	 * UIDs are not guaranteed to have a persistent 1to1 relation with the term identity. 
	 * When GC kicks in, an IRI ( for example ) can be garbage collected and its UID will be lost.
	 * The next time it is requested, a new UID is assigned.
	 * Therefore, you cannot rely on UIDs to identify RDFValues unless you keep a reference to the term as well.
	 * </p>
	 * 
	 * 
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */
	public class RDFValue implements IRDFValueHolder, IUID, IValueSingleton
	{
	
	
	
		private var _uid:String;

		public function get uid( ):String
		{
			if ( _uid == null ) // lazy creation... it is a string after all
				_uid = UIDUtil.createUID( );
			return _uid;
		}
		
		public function set uid( v:String ):void
		{
			// do nothing, we set it internally.		
		}
		
		
		
		


		
		public function RDFValue( )
		{
				
		}
		
		
		
		// abstract
		public function get nt( ):String
		{
			return null;
		}
		
		public function get rdfValue( ):RDFValue
		{
			return this;
		}		
		
		
		/**
		 * 
		 * The equivalent value in the AS3 value space
		 * 
		 * @return 
		 * 
		 */		
		public function get as3Value( ):*
		{
			return RDFValueCodec.toAS3( this );
		}
		
		
		
		/**
		 * Returns a URL string for this RDF value, if any.
		 * If this is an IRI, then it will return the IRI's stringForm.
		 * If this is a plain literal or an xsd:string typed literal, it will check for the http protocol and
		 * return the lexical value if found.
		 * 
		 * The main usecase for this is when passing an rdfvalue as the value for a url. For example to mx.controls.Image.source
		 * 
		 * @return 
		 * 
		 */
		public function get asPlainURL( ):String{
			if ( this is IRI )
				return ( this as IRI ).stringForm;
			if ( this is RDFLiteral )
			{
				var l:RDFLiteral = this as RDFLiteral;
				if ( l.lexicalValue.indexOf( "http" ) == 0 )
					return l.lexicalValue;
			}
			return null;
		}


		/**
		 * 
		 * Returns the string representation of this RDF Term.
		 * It uses NTriple serialization, so remember:
		 * <p>
		 * <b>IRIs will are wrapped between &lt; and &gt; </b>
		 * </p>
		 * 
		 * @return 
		 * 
		 */
		public function toString( ):String
		{
		
			return this.nt;
		
		}







		////////////////////////////////////////////////////////////
		/////////////////////////// static /////////////////////////		
		////////////////////////////////////////////////////////////



		/**
		 * 
		 * This is used by subclasses. We put it here to centralize if we need to change it later.
		 * 
		 * @param str
		 * @return 
		 * 
		 */
		internal static function hash( str:String ):String
		{
			return MD5.hash( str );
		}


		
		
		////////////////////////////////////////////////////////////
		/////////////////////////// cache //////////////////////////		
		////////////////////////////////////////////////////////////



		internal static function getCachedValue( key:String ):RDFValue
		{
			if ( RDFValueCache.i.cache[ key ] )
			{
				return RDFValueCache.i.cache[ key ] as RDFValue;
			}
			return null;
		}
		
		
		/**
		 * 
		 * @param key
		 * @param value
		 * @return the value ( for code cascading )
		 * 
		 */		
		internal static function cacheValue( key:String, value:RDFValue ):RDFValue
		{
			RDFValueCache.i.cache[ key ] = value;
			return value;
		}		
		
	}

}